package com.sc.sc250601.cook.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sc.sc250601.cook.mapper.FavoriteMapper;
import com.sc.sc250601.cook.mapper.RecipeMapper;
import com.sc.sc250601.cook.pojo.Favorite;
import com.sc.sc250601.cook.pojo.Recipe;
import com.sc.sc250601.cook.service.RecipeService;
import lombok.extern.log4j.Log4j;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Log4j2
@Service
public class RecipeServiceImpl implements RecipeService {

    @Autowired
    private RecipeMapper recipeMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    private static final ObjectMapper mapper = new ObjectMapper();

    /**
     * 获取本周最热菜谱20
     * @return
     */
    @Override
    public List<Recipe> weekTop() {
        // TODO 可以优化: 定时任务、缓存、长度为20的大顶堆、一次查询20个菜谱和用户信息
        // 读取一周的菜谱
        List<Recipe> recipes = recipeMapper.weekTop();
        if(recipes == null){
            return null;
        }
        // 遍历菜谱，根据浏览量、点赞量、收藏量加权排序
        Map<Long, Integer> pointMap = new HashMap<>();
        for(Recipe recipe : recipes){
            int point = 0;
            point += recipe.getViewCount();
            point += recipe.getLikeCount() * 2;
            point += recipe.getCollectCount() * 3;
            pointMap.put(recipe.getId(), point);
        }
        // 按照 value 降序排序
        List<Map.Entry<Long, Integer>> sortedEntries = pointMap.entrySet()
                .stream()
                .sorted(Map.Entry.<Long, Integer>comparingByValue().reversed())
                .collect(Collectors.toList());
        // 获取排序后的菜谱id
        List<Long> sortedIds = sortedEntries.stream().map(Map.Entry::getKey).collect(Collectors.toList());
        System.out.println("sortedIds:" + sortedIds);
        // 返回对应菜谱的对应用户
        return recipeMapper.selectByIdsWithUser(sortedIds);
    }

    /**
     * 获取本周最热菜谱20
     * 1.14 -> 57
     * @return
     */
    @Override
    public List<Recipe> weekTop1() {

        String topKey = "cook:recipe:weekTop";

        try {
            String cached = redisTemplate.opsForValue().get(topKey);
            if (cached != null) {
                // 使用 TypeReference 解决泛型擦除问题
                return mapper.readValue(cached, new TypeReference<List<Recipe>>() {});
            }
        } catch (Exception e) {
            // 记录日志而不是打印堆栈
            log.warn("Failed to read cache for weekTop", e);
        }

        // 读取一周的菜谱
        List<Recipe> recipes = recipeMapper.weekTop();
        if (recipes == null || recipes.isEmpty()) {
            return Collections.emptyList();
        }

        Map<Long, Integer> pointMap = new HashMap<>();
        for(Recipe recipe : recipes){
            int point = 0;
            point += recipe.getViewCount();
            point += recipe.getLikeCount() * 2;
            point += recipe.getCollectCount() * 3;
            pointMap.put(recipe.getId(), point);
        }
        // 按照 value 降序排序
        List<Map.Entry<Long, Integer>> sortedEntries = pointMap.entrySet()
                .stream()
                .sorted(Map.Entry.<Long, Integer>comparingByValue().reversed())
                .collect(Collectors.toList());
        // 获取排序后的菜谱id
        List<Long> sortedIds = sortedEntries.stream().map(Map.Entry::getKey).collect(Collectors.toList());
        List<Recipe> recipesTop = recipeMapper.selectByIdsWithUser(sortedIds);

        try {
            redisTemplate.opsForValue().set(topKey, mapper.writeValueAsString(recipesTop),10, TimeUnit.MINUTES);
        } catch (Exception e) {
            log.warn("Failed to write cache for weekTop", e);
        }
        return recipesTop;
    }

    /**
     * 获取本周最热菜谱20
     * 952 -> 57
     * @return
     */
    @Override
    public List<Recipe> weekTop2() {
        String topKey = "cook:recipe:weekTop";

        // 1. 读缓存
        try {
            String cached = redisTemplate.opsForValue().get(topKey);
            if (cached != null) {
                return mapper.readValue(cached, new TypeReference<List<Recipe>>() {});
            }
        } catch (Exception e) {
            log.warn("Failed to read cache for weekTop, evicting...", e);
            redisTemplate.delete(topKey);
        }

        // 2. 查数据库（SQL 已经算好分数和排序）
        List<Recipe> recipesTop = recipeMapper.weekTop2();
        if (recipesTop == null || recipesTop.isEmpty()) {
            return Collections.emptyList();
        }

        // 3. 写缓存，加 TTL
        try {
            redisTemplate.opsForValue().set(
                    topKey,
                    mapper.writeValueAsString(recipesTop),
                    10, TimeUnit.MINUTES);  // 10分钟有效期，可按需调整
        } catch (Exception e) {
            log.warn("Failed to write cache for weekTop", e);
        }

        return recipesTop;
    }



    /**
     * 获取收藏量top20
     * @return
     */
    @Override
    public List<Recipe> favoriteTop() {
        return recipeMapper.favoriteTop();
    }

    @Override
    public List<Recipe> getRecipesByType(String type) {
        return  recipeMapper.getRecipesByType(type);
    }

    @Override
    public Recipe getRecipeById(Long id) {
        return recipeMapper.selectOneRecipeWithUser(id);
    }

    /**
     * 添加菜谱
     * @param r
     *
     */
    @Override
    public int addRecipe(Recipe r) {
        return recipeMapper.insert(r);
    }

    @Override
    public List<Recipe> getRecipes() {
        return recipeMapper.selectAllRecipe();
    }

    @Override
    public int addViewCount(Long id) {
        return recipeMapper.updateViewCount( id);
    }


    @Override
    public List<Recipe> getRecipeListByUserId(Long userId) {
        return recipeMapper.selectRecipeByUserId(userId);
    }


}
